package com.tentcoo.core.event;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.tentcoo.util.AssertUtils;
import com.tentcoo.util.ReflectionUtils;

public class EventManager {

	private static final Logger LOGGER = LoggerFactory
			.getLogger(EventManager.class);
	private static final String EVENT_LISTENER_ACTION_METHOD_NAME = "action";

	private static final Multimap<Class<? extends Event>, EventListener<?>> eventHooker = LinkedHashMultimap
			.create();

	public synchronized static void bind(EventListener<?> eventListener) {
		bind(eventListener, false);
	}

	public synchronized static void bind(EventListener<?> eventListener,
			boolean temporary) {
		AssertUtils.notNull(eventListener);

		eventListener.setTemporary(temporary);
		Class<? extends Event> eventClass = eventListener.getEventClass();
		if (!eventHooker.containsEntry(eventClass, eventListener)) {
			eventHooker.put(eventClass, eventListener);
			LOGGER.debug(eventListener + "正在监听" + eventClass);
		} else {
			LOGGER.warn("没法重复注册同一个监听器" + eventListener);
		}
	}

	public synchronized static void unbind(EventListener<?> eventListener) {
		AssertUtils.notNull(eventListener);

		Class<? extends Event> eventClass = eventListener.getEventClass();
		boolean result = eventHooker.remove(eventClass, eventListener);
		if (result) {
			LOGGER.debug("移除" + eventListener + "对" + eventClass + "的监听");
		} else {
			LOGGER.debug("监听器" + eventListener + "没被注册");
		}

	}

	public synchronized static void removeEvent(
			Class<? extends Event> eventClass) {
		AssertUtils.notNull(eventClass);

		eventHooker.removeAll(eventClass);
		LOGGER.debug("移除" + eventClass + "的所有监听器");
	}

	public static void fire(Event event) {
		AssertUtils.notNull(event);
		Object eventSource = event.getEventSource();
		AssertUtils.notNull(eventSource);

		Class<? extends Event> eventClass = event.getClass();
		if (!eventHooker.containsKey(eventClass)) {
			LOGGER.debug("没有监听器监听事件" + eventClass);
			return;
		}

		Collection<EventListener<?>> eventListeners = eventHooker
				.get(eventClass);
		// 遍历监听该事件的事件监听器
		for (Iterator<EventListener<?>> iterator = eventListeners.iterator(); iterator
				.hasNext();) {
			EventListener<?> eventListener = iterator.next();
			synchronized (eventListener) {
				try {
					// 反射执行action方法
					Method action = eventListener.getClass().getMethod(
							EVENT_LISTENER_ACTION_METHOD_NAME, eventClass);
					action.invoke(eventListener, event);
					LOGGER.debug("监听到" + eventClass + ",激活监听器" + eventListener);
				} catch (Exception ex) {
					ReflectionUtils.handleReflectionException(ex);
				} finally {
					// 如果监听器是临时监听器，移除之
					if (eventListener.isTemporary()) {
						unbind(eventListener);
					}
				}
			}
		}
	}
}
